/*
Copyright (c) [2022] [shawnping]
[masm-assistant] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2. 
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2 
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
See the Mulan PSL v2 for more details.
*/
/*                ███╗   ███╗ █████╗ ███████╗███╗   ███╗                    */
/*                ████╗ ████║██╔══██╗██╔════╝████╗ ████║                    */
/*                ██╔████╔██║███████║███████╗██╔████╔██║                    */
/*                ██║╚██╔╝██║██╔══██║╚════██║██║╚██╔╝██║                    */
/*                ██║ ╚═╝ ██║██║  ██║███████║██║ ╚═╝ ██║                    */
/*                ╚═╝     ╚═╝╚═╝  ╚═╝╚══════╝╚═╝     ╚═╝                    */
/*                                                                          */
/*   █████╗ ███████╗███████╗██╗███████╗████████╗ █████╗ ███╗   ██╗████████╗ */
/*  ██╔══██╗██╔════╝██╔════╝██║██╔════╝╚══██╔══╝██╔══██╗████╗  ██║╚══██╔══╝ */
/*  ███████║███████╗███████╗██║███████╗   ██║   ███████║██╔██╗ ██║   ██║    */
/*  ██╔══██║╚════██║╚════██║██║╚════██║   ██║   ██╔══██║██║╚██╗██║   ██║    */
/*  ██║  ██║███████║███████║██║███████║   ██║   ██║  ██║██║ ╚████║   ██║    */
/*  ╚═╝  ╚═╝╚══════╝╚══════╝╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═══╝   ╚═╝    */

/*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
关键字与文法结构的基础接口
/*////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 


import { debug, group } from 'console';
import * as vscode from 'vscode';

/*文本选择器默认值*/
export const selector: vscode.DocumentSelector = { scheme: 'file', language: 'micro-soft-macro-assembler' };





/*关键字基类*/
export interface IReservedWord {
    word: string
    brief?: string
    commit?: string[]
}

/*********************************************************************/
//参数类型
/*********************************************************************/
/*枚举型参数组*/
interface IParaEnum {
    paraType: string
    trigger: string[]
    enumPara: IReservedWord[]
}
/*带子选项的参数组*/
interface IParaWithSubEnumPara {
    paraKeyword: IReservedWord
    trigger: string
    subPara: IParaEnum
}

interface IPara {
    isOptional: boolean
    paraObj: (IParaEnum | IParaWithSubEnumPara)
}
/*===================================================================*/
/*===================================================================*/



/*带枚举参数和常量参数的伪指令*/
interface IDirectiveWE {
    key: IReservedWord
    paraList: IPara[]
}


/*指令组*/
export interface IReservedWordGroup {
    groupName: string
    casemap: boolean
    isUsing: boolean
    keywords: (IReservedWord | IDirectiveWE)[]
}

/*类型*/
export enum MASMType {
    struct,
    union,
    record,
    distance,
    dataType,
    typeId,
}

interface ICompList {
    trigger: string
    comList: vscode.CompletionList
}

interface ICompDirInsWE{
    matchMode:RegExp[]
}

/*类型检查*/
export function instanceOfIRservedWord(object: any): object is IReservedWord { return 'word' in object; }
export function instanceOfIDirectiveWE(object: any): object is IDirectiveWE { return 'key' in object; }
function instanceOfIEnum(object: any): object is IParaEnum { return 'enumPara' in object; }
function instanceOfIParaWithSubEnumPara(object: any): object is IParaWithSubEnumPara { return 'paraKeyword' in object; }

/*生成大写关键字*/
export function reservedWordsUpper(...reservedWords: (IReservedWordGroup[])[]) {
    let rwGroup: IReservedWordGroup[] = [];
    let rwGroupUpper: IReservedWordGroup[] = [];
    reservedWords.forEach((groups) => {
        groups.forEach((group) => {
            rwGroupUpper.push(
                {
                    groupName: group.groupName,
                    casemap: group.casemap,
                    isUsing: group.isUsing,
                    keywords: JSON.parse(JSON.stringify(group.keywords))
                }
            );
            rwGroup.push(
                {
                    groupName: group.groupName,
                    casemap: group.casemap,
                    isUsing: group.isUsing,
                    keywords: JSON.parse(JSON.stringify(group.keywords))
                }
            );
        });
    });
    rwGroupUpper.forEach((group) => {
        if (!group.casemap) {
            group.keywords.forEach((keyword) => {
                if (instanceOfIRservedWord(keyword)) {
                    keyword.word = keyword.word.toUpperCase();
                }
                else if (instanceOfIDirectiveWE(keyword)) {
                    keyword.key.word = keyword.key.word.toUpperCase();
                    keyword.paraList.forEach((val) => {
                        if (instanceOfIEnum(val)) {
                            val.enumPara.forEach((rw) => {
                                rw.word = rw.word.toUpperCase();
                            });
                        }
                        else if (instanceOfIParaWithSubEnumPara(val)) {
                            val.paraKeyword.word = val.paraKeyword.word.toUpperCase();
                            val.subPara.enumPara.forEach((enumWord) => {
                                enumWord.word = enumWord.word.toUpperCase();
                            });
                        }
                    });
                }
            });
        }
    });
    return { upper: rwGroupUpper, lower: rwGroup };
}

/*指令参数Completion*/
export function reservedWordToCompletionPara(reservedWords:IReservedWordGroup[]) {
    reservedWords.forEach((group)=>{
        if(group.isUsing){
            group.keywords.forEach((keyword)=>{
                if(instanceOfIDirectiveWE(keyword)){
                }
            });
        }
    });
}

/*保留字转CompletionItem*/
export function reservedWordToCompletion(reservedwords: IReservedWordGroup[]) {
    let headWord: vscode.CompletionList = new vscode.CompletionList();

    let headNoWord: ICompList[] = [];

    reservedwords.forEach((group) => {
        group.keywords.forEach((rw) => {
            if (instanceOfIRservedWord(rw)) {
                headWord.items.push(
                    {
                        label: rw.word,
                        documentation: new vscode.MarkdownString(rw.brief),
                        kind: vscode.CompletionItemKind.Keyword
                    }
                );
                if (rw.word.match(/^\W/) !== null) {
                    let temp: vscode.CompletionItem = { 
                        label: rw.word, 
                        documentation: new vscode.MarkdownString(rw.brief), 
                        commitCharacters: rw.commit, 
                        insertText: rw.word.substring(1), 
                        kind: vscode.CompletionItemKind.Keyword 
                    };


                    if (headNoWord.length === 0) {
                        headNoWord.push(
                            {
                                trigger: rw.word.substring(0, 1),
                                comList: new vscode.CompletionList([temp])
                            }
                        );
                    }
                    else {

                        let isHaving = false;

                        for (let i = 0; i < headNoWord.length; i++) {
                            if (headNoWord[i].trigger === rw.word.substring(0, 1)) {
                                headNoWord[i].comList.items.push(temp);
                                isHaving = true;
                                break;
                            }
                        }

                        if (!isHaving) {
                            headNoWord.push(
                                {
                                    trigger: rw.word.substring(0, 1),
                                    comList: new vscode.CompletionList([temp])
                                }
                            );
                        }
                    }
                }
            }
            else if (instanceOfIDirectiveWE(rw)) {
                headWord.items.push(
                    { label: rw.key.word, documentation: new vscode.MarkdownString(rw.key.brief) }
                );
                if (rw.key.word.match(/\W/) !== null) {
                    let temp: vscode.CompletionItem = { label: rw.key.word, documentation: rw.key.brief, commitCharacters: rw.key.commit, insertText: rw.key.word.substring(1) };
                    if (headNoWord.length === 0) {
                        headNoWord.push(
                            {
                                trigger: rw.key.word.substring(0, 1),
                                comList: new vscode.CompletionList([temp])
                            }
                        );
                    }
                    else {

                        let isHaving = false;

                        for (let i = 0; i < headNoWord.length; i++) {
                            if (headNoWord[i].trigger === rw.key.word.substring(0, 1)) {
                                headNoWord[i].comList.items.push(temp);
                                isHaving = true;
                                break;
                            }
                        }

                        if (!isHaving) {
                            headNoWord.push(
                                {
                                    trigger: rw.key.word.substring(0, 1),
                                    comList: new vscode.CompletionList([temp])
                                }
                            );
                        }
                    }
                }
            }
        });
    });


    return {
        headWord: headWord,
        headNoWord: headNoWord,
    };
}
